#include "OamManager.h"
#include "SnifferManager.h"
#include "MessageDef.h"
#include "EutranConfigData.h"
#ifdef ignore
#undef ignore
#endif
#include <sstream>
#include <iomanip>
#include "eutranMsgHandle.h"


OamManager::OamManager()
{
}

OamManager* OamManager::instance()
{
    static OamManager instance_;
    return &instance_;
}

void OamManager::processOamMessage(TlvMessage& tlvMsg, in_addr_t peerAddr)
{
    BbuCtrl* bbu = BbuManagerPtr->getBbu(peerAddr);
    if( bbu==NULL )
    {
        EMLogError("Fail to get BBU from ip[0x%x]", ntohl(peerAddr));
        return;
    }

    if( !bbu->getInstance().isActive() )
    {
        if( !(tlvMsg.getProtocolType()==NmmToX86Protocol_Signal::TLV_PROTOCOL_NUMBER && 
               tlvMsg.getSignalType()==NmmToX86Protocol_Signal::INIT_NOTIFICATION) )
        {
            EMLogWarning("BBU[%d]: Not init but recv msg[%d:%d]", bbu->getInstance().getSlotId(), tlvMsg.getProtocolType(), tlvMsg.getSignalType());
            return;
        }
    }
    
    if( tlvMsg.getProtocolType()==NmmToX86Protocol_Signal::TLV_PROTOCOL_NUMBER )
    {
        switch(tlvMsg.getSignalType())
        {
            case NmmToX86Protocol_Signal::UE_REDIRECT_RSP:
            {
                NmmToX86Protocol_UeRedirectRsp msg(tlvMsg);
                processUeRedirectRsp(msg, *bbu);
                break;
            }
            case NmmToX86Protocol_Signal::INIT_NOTIFICATION:
            {
                NmmToX86Protocol_InitNotification initNotify(tlvMsg);
                processInitNotification(initNotify, *bbu);
                break;
            }
            case NmmToX86Protocol_Signal::HEARBEAT:
            case NmmToX86Protocol_Signal::HEARBEAT_ACK:
            {
                NmmToX86Protocol_HeartBeat hb(tlvMsg);
                processHBAck(hb, *bbu);
                break;
            }
            case NmmToX86Protocol_Signal::CELL_CONFIG_RSP:
            {
                NmmToX86Protocol_CellConfigRsp cfgRsp(tlvMsg);
                processCellCfgRsp(cfgRsp, *bbu);
                break;
            }
            case NmmToX86Protocol_Signal::CELL_UPDATE_RSP:
            {
                EMLogInfo("BBU[%d]: recevie CELL_UPDATE_RSP", bbu->getInstance().getSlotId());
                break;
            }
            default:
            {
                EMLogError("Unkown NMM message type[%d]", static_cast<uint32_t>(tlvMsg.getSignalType()));
                break;
            }
        }
    }
    else if( OamMessageProtocol_Signal::TLV_PROTOCOL_NUMBER )
    {
        switch(tlvMsg.getSignalType())
        {
            case OamMessageProtocol_Signal::NMM_DELAY_REPORT_MSG:
            {
                OamMessageProtocol_NmmDelayReport bbuMsg(tlvMsg);
                processNmmDelayReport(bbuMsg, *bbu);
                break;
            }
            case OamMessageProtocol_Signal::INIT_CFG_COMP:
            {
                EMLogInfo("BBU[%d] complete init config", bbu->getInstance().getSlotId());
                OamMessageProtocol_InitCfgComp cfgComp(tlvMsg);
                processInitCfgComp(cfgComp, *bbu);
                break;
            }
            case OamMessageProtocol_Signal::SYSTEM_TIME_RSP:
            {
                OamMessageProtocol_SysTimeRsp rsp(tlvMsg);
                uint8_t rc = 0;
                if( !rsp.unpack(rc) )
                {
                    EMLogWarning("Fail to unpack SysTimeRsp");
                }
                EMLogInfo("Receive SysTimeRsp[rc=%d] from BBU[%d]", static_cast<uint32_t>(rc), bbu->getInstance().getSlotId());
                break;
            }
            case OamMessageProtocol_Signal::SOFTWARE_INFO_REPORT:
            {
                OamMessageProtocol_VersionRpt verRpt(tlvMsg);
                processSoftwareVerRpt(verRpt, bbu->getInstance().getSlotId());
                break;
            }
            case OamMessageProtocol_Signal::UEID_FILTER_CFG_RSP:
            {
                OamMessageProtocol_UeIdFilterSwitchCfgRsp oamMsg(tlvMsg);
                processUeIdFilterRsp(oamMsg, *bbu);
                break;
            }
            case OamMessageProtocol_Signal::TX_POWER_DBM_STD_GET_RSP:
            {
                EMLogInfo("Receive TX_POWER_DBM_STD_GET_RSP from BBU[%d]", bbu->getInstance().getSlotId());
                OamMessageProtocol_TxPowerDbmStdGetRsp oamMsg(tlvMsg);
                processStdTxPowerDbGetRsp(oamMsg, *bbu);
                break;
            }
            case OamMessageProtocol_Signal::TX_POWER_STD_CFG_RSP:
            {
                EMLogInfo("Receive TX_POWER_STD_RSP from BBU[%d]", bbu->getInstance().getSlotId());
                OamMessageProtocol_TxPowerStdCfgRsp oamMsg(tlvMsg);
                processStdTxPowerCfgRsp(oamMsg, *bbu);
                break;
            }
            case OamMessageProtocol_Signal::TX_POWER_STD_GET_RSP:
            {
                OamMessageProtocol_TxPowerStdGetRsp oamMsg(tlvMsg);
                processStdTxPowerGetRsp(oamMsg, *bbu);
                break;
            }
            case OamMessageProtocol_Signal::TX_POWER_ATT_RSP:
            {
                EMLogError("Receive TX_POWER_ATT_RSP from BBU[%d]", bbu->getInstance().getSlotId());

                break;
            }
            case OamMessageProtocol_Signal::TX_POWER_DBM_CONFIG_RSP:
            {
                EMLogInfo("Receive TX_POWER_DBM_CONFIG_RSP from BBU[%d]", bbu->getInstance().getSlotId());

                OamMessageProtocol_TxPowerDbmConfigRsp txPwDbRsp(tlvMsg);
                SnifferMgrPtr->processTxPwerDbRsp(*bbu, txPwDbRsp);
                processTxPowerDbCfgRsp(txPwDbRsp, *bbu);
                break;
            }
            case OamMessageProtocol_Signal::SYSTEM_STATUS_REPORT:
            {
                EMLogInfo("Receive SYSTEM_STATUS_REPORT from BBU[%d]", bbu->getInstance().getSlotId());
                OamMessageProtocol_SysStatusRsp rpt(tlvMsg);
                processBbuStatusRpt(rpt, *bbu);
                break;
            }
            case OamMessageProtocol_Signal::SOFTWARE_UPGRADE_RSP:
            {
                EMLogInfo("Receive SOFTWARE_UPGRADE_RSP from BBU[%d]", bbu->getInstance().getSlotId());
                OamMessageProtocol_SoftwareUpgradRsp rpt(tlvMsg);
                processBbuUpgradeRsp(rpt, *bbu);
                break;
            }
            case OamMessageProtocol_Signal::EQUIP_RESET_RSP:
            {
                EMLogInfo("Receive EQUIP_RESET_RSP from BBU[%d]", bbu->getInstance().getSlotId());
                OamMessageProtocol_EquipResetRsp rsp(tlvMsg);
                processEquitResetRsp(rsp, *bbu);
                break;
            }
            case OamMessageProtocol_Signal::SYNC_MODE_RSP:
            {
                OamMessageProtocol_SyncModeRsp rsp(tlvMsg);
                processSyncModeSettingRsp(rsp, *bbu);
                break;
            }
            case OamMessageProtocol_Signal::SYNC_STATUS_REPORT:
            {
                OamMessageProtocol_SyncStatusRsp rsp(tlvMsg);
                processSyncStateRsp(rsp, *bbu);
                break;
            }
            case OamMessageProtocol_Signal::EQUIP_RESET_ACCI:
            {
                EMLogInfo("BBU[%d] reset accidentally", bbu->getInstance().getSlotId());
                break;
            }
            case OamMessageProtocol_Signal::GPS_INFO_REPORT:
            {
                OamMessageProtocol_GpsInfoRpt rsp(tlvMsg);
                processGpsStateRsp(rsp, *bbu);
                break;
            }
            case OamMessageProtocol_Signal::RX_LEV_MIN_CFG_RSP:
            {
                OamMessageProtocol_RxLevMinCfgRsp rsp(tlvMsg);
                uint8_t rc = 0;
                if( !rsp.unpack(rc) )
                {
                    EMLogError("BBU[%d]: Fail to unpack RX_LEV_MIN_CFG_RSP", bbu->getInstance().getSlotId());
                    break;
                }
                EMLogInfo("BBU[%d]: receive RX_LEV_MIN_CFG_RSP[rc=%d]", bbu->getInstance().getSlotId(), static_cast<uint32_t>(rc));                
                break;
            }
            case OamMessageProtocol_Signal::LOCATION_MODE_SETTING_RSP:
            {
                OamMessageProtocol_LocationModeSettingRsp bbuMsg(tlvMsg);
                uint8_t rc = 0;
                if( !bbuMsg.unpack(rc) )
                {
                    EMLogError("BBU[%d]: Fail to unpack LOCATION_MODE_SETTING_RSP", bbu->getInstance().getSlotId());
                    break;
                }
                EMLogInfo("BBU[%d]: receive LOCATION_MODE_SETTING_RSP[rc=%d]", bbu->getInstance().getSlotId(), static_cast<uint32_t>(rc));
                break;
            }
            case OamMessageProtocol_Signal::ALARM_RPT:
            {
                break;
            }
            default:
            {
                EMLogError("Unkown NMM message type[%d]", static_cast<uint32_t>(tlvMsg.getSignalType()));
                break;
            }
        }
    }
/*
    uint16_t key = tlvMsg.getProtocolType();
    key = (key << 8)|tlvMsg.getSignalType();
    std::map<uint16_t, std::list<EmBaseProcedure*> >::iterator fit = procHandlers_.find(key);
    if( fit!=procHandlers_.end() )
    {
        std::list<EmBaseProcedure*> procs = fit->second;

        procHandlers_.erase(fit);

        for(std::list<EmBaseProcedure*>::iterator it=procs.begin(); it!=procs.end(); it++)
        {
            (*it)->processMessage(tlvMsg, *bbu);
        }
    }*/
}

void OamManager::processInitCfgComp(OamMessageProtocol_InitCfgComp& comp, BbuCtrl& bbu)
{
    uint8_t rc = 0;
    if( !comp.unpack(rc) )
    {
        EMLogError("BBU[%d]: Fail to unpack RC of InitCfgComp message", bbu.getInstance().getSlotId());
    }

    bbu.setInitCfgComp(true);
    bbu.buildAndSendSysTimeSync();
    bbu.buildAndSendMinRxLev();
    shutDownTxPwer(bbu);

    if( SnifferMgrPtr->isSniffering(bbu.getInstance().getSlotId()) )
    {
        StateReportProcedurePtr->reportState(bbu, BBU_SNFING);
    }
    else
    {
        StateReportProcedurePtr->reportState(bbu, BBU_READY);
    }
}

void OamManager::processUeRedirectRsp(NmmToX86Protocol_UeRedirectRsp& msg, BbuCtrl& bbu)
{
    uint8_t rc = 0;
    if( !msg.unpack(rc) )
    {
        EMLogError("BBU[%d]: Fail to unpack UeRedirectRsp", bbu.getInstance().getSlotId());

        if( isTrgByOam_ )
        {
            isTrgByOam_ = false;
            EutranMgrPtr->responseFailure();
            return;
        }
    }

    if( rc!=0 )
    {
        EMLogError("BBU[%d]: Fail to set UE redirect. RC=%d", bbu.getInstance().getSlotId(), static_cast<uint32_t>(rc));

        if( isTrgByOam_ )
        {
            isTrgByOam_ = false;
            EutranMgrPtr->responseFailure();
            return;
        }
    }

    EutranMgrPtr->responseSuccess();
}

void OamManager::processNmmDelayReport(OamMessageProtocol_NmmDelayReport& msg, BbuCtrl& bbu)
{
    std::string imsi;
    uint16_t delay = 0;
    uint32_t sinr = 0;
    uint16_t rsrp = 0;
    uint16_t ulArfcn = 0;
    if( !msg.unpack(imsi, delay, sinr, rsrp, ulArfcn) )
    {
        EMLogError("Fail to unpack NmmDelayReport");
        return;
    }
	if(bbu.getInstance().getSlotId() == 6 || bbu.getInstance().getSlotId() == 7)
	{
		sinr = (uint32_t)(sinr/2);
	}
    EMLogDebug("BBU[%d]: IMSI[%s], delay[%d], SINR[%d] RSRP[%d] ulArfcn[%d]", bbu.getInstance().getSlotId(), imsi.c_str(), delay, sinr, rsrp, ulArfcn);

    std::vector < WrapperCmdPara > reportParas;
    uint8_t tmpbuf1[128] = {0};
    memset(&tmpbuf1[0], 0, sizeof(tmpbuf1));
    memcpy(&tmpbuf1[0], imsi.c_str(), imsi.length());
    tmpbuf1[imsi.length()] = '\0';
    reportParas.push_back(WrapperCmdPara(PARA_TYPE_EUTRAN_UEID_IMSI, imsi.length()+1, &tmpbuf1[0]));
    reportParas.push_back(WrapperCmdPara(PARA_TYPE_EUTRAN_NMM_DELAY, delay));
    reportParas.push_back(WrapperCmdPara(PARA_TYPE_EUTRAN_NMM_SINR, sinr));
 //   reportParas.push_back(WrapperCmdPara(PARA_TYPE_EUTRAN_DL_ARFCN, bbu.getWorkingDlArfcn()));
    reportParas.push_back(WrapperCmdPara(PARA_TYPE_EUTRAN_BBU_SLOT_ID, bbu.getInstance().getSlotId()));    
    reportParas.push_back(WrapperCmdPara(PARA_TYPE_EUTRAN_RSRP, rsrp));
    reportParas.push_back(WrapperCmdPara(PARA_TYPE_EUTRAN_UL_ARFCN, ulArfcn));
	reportParas.push_back(WrapperCmdPara(PARA_TYPE_EUTRAN_PCI, bbu.getWorkingPci()));
    EutranMgrPtr->reportInfo(CMD_EVT_EUTRAN_NMM_DELAY_REPORT, reportParas);
}

void OamManager::processInitNotification(NmmToX86Protocol_InitNotification& init, BbuCtrl& bbu)
{
    
    BbuInstance& instanceData = bbu.getInstance();

    uint32_t recvSeqNo = 0;

    uint8_t bandSupport = 0;
    uint8_t isFddSupport = 0;
    if( !init.unpack(bandSupport, isFddSupport) )
    {
        EMLogError("BBI[%d]: Fail to unpack NmmToX86Protocol_InitNotification", instanceData.getSlotId());
        return;
    }

    EMLogInfo("BBU[%d]: Receive INIT_NOTIFICATION that bandSupport[%d] and isFddSupport[%d]", 
               instanceData.getSlotId(), bandSupport, isFddSupport);

    if( isFddSupport && FDD!=instanceData.getDuplexMode())
    {
        EMLogWarning("Inconsistent duplex mode[%s] with pre-set[%s]", "FDD", "TDD");
    }

    if( !isFddSupport && TDD!=instanceData.getDuplexMode())
    {
        EMLogWarning("Inconsistent duplex mode[%s] with pre-set[%s]", "TDD", "FDD");
    }

    if( (bandSupport & 0x01) && !instanceData.IsBandSupported(9))
    {
        EMLogWarning("Pre-setting not support B9, add it");
        instanceData.addBandSupported(9);
    }
    if( (bandSupport & 0x02) && !instanceData.IsBandSupported(38))
    {
        EMLogWarning("Pre-setting not support B38, add it");
        instanceData.addBandSupported(38);
    }
    if( (bandSupport & 0x04) && !instanceData.IsBandSupported(39))
    {
        EMLogWarning("Pre-setting not support B39, add it");
        instanceData.addBandSupported(39);
    }
    if( (bandSupport & 0x08) && !instanceData.IsBandSupported(40))
    {
        EMLogWarning("Pre-setting not support B40, add it");
        instanceData.addBandSupported(40);
    }

    if( instanceData.isActive() )
    {
        EMLogWarning("BBU[%d]: Become active but not detect inactive state", instanceData.getSlotId());
        bbu.indicateDeactive();
    }

    bbu.connEstablish();

    NmmToX86Protocol_InitNotificationRsp initNotiRsp;
    initNotiRsp.packSeqNum(recvSeqNo);

    bbu.indicateAactive();
    instanceData.sendMessage(initNotiRsp.getMessage());

    bbu.buildAndSendInitCfg();
    StateReportProcedurePtr->reportState(bbu, BBU_INIT_CFG);
}

void OamManager::processHBAck(NmmToX86Protocol_HeartBeat& hbAck, BbuCtrl& bbu)
{
    BbuInstance& instanceData = bbu.getInstance();

    instanceData.setHearBeatAckRecv(true);
}

void OamManager::processCellCfgRsp(NmmToX86Protocol_CellConfigRsp& cfgRsp, BbuCtrl& bbu)
{
    uint8_t rc = 0;
    if( !cfgRsp.unpack(rc) )
    {
        EMLogError("Fail to unpack CellConfigRsp");
        if( isTrgByOam_ )
        {
            isTrgByOam_ = false;

            std::vector < WrapperCmdPara > responseParas;
            responseParas.push_back(WrapperCmdPara(PARA_TYPE_RESULT, static_cast<uint32_t>(PARA_VALUE_RESULT_FAILED)));
            EutranMgrPtr->responseToSrcModule(CMD_SET_RESPONSE, responseParas);
            return;
        }
    }

    std::vector < WrapperCmdPara > responseParas;
    if( rc==0 )
    {
        bbu.handleCtrlPA(true, BbuCtrl::DO_NOTHING);
		bbu.setWorking(true);
        EMLogInfo("BBU[%d]: Success to  cell config rsp", bbu.getInstance().getSlotId());
        responseParas.push_back(WrapperCmdPara(PARA_TYPE_RESULT, static_cast<uint32_t>(PARA_VALUE_RESULT_SUCCESS)));
        int8_t txPwDb = EutranConfigDataPtr->getTxPowerDb(bbu.getInstance().getSlotId());
        EMLogInfo("BBU[%d]: open TX power[%d]", bbu.getInstance().getSlotId(), static_cast<int32_t>(txPwDb));
		if (BbuManagerPtr->isLocationMode())
		{
			if (BbuManagerPtr->getLocationEnable(bbu.getInstance().getDuplexMode()))
			{	
				bbu.buildAndSendTxPowerDb(txPwDb);
				if (BbuManagerPtr->getLocationEnable(bbu.getInstance().getDuplexMode()))
				{
					std::vector<std::string> tagImsi;
					BbuManagerPtr->getLocationImsi(tagImsi);
					bbu.buidlAndSendLocModeSetting(true, tagImsi);
				}

			}
		}
		else
		{
			if(!SnifferMgrPtr->isSniffering() )
			{
				bbu.buildAndSendTxPowerDb(txPwDb);
			}
			else
			{
				EMLogInfo("BBU[%d]: wait sniffer done to open TX power", bbu.getInstance().getSlotId());
			}
		}
        StateReportProcedurePtr->reportState(bbu, BBU_LOCATION);

        int index =  bbu.getInstance().getSlotId() - 1;
        UE_REDIRECT *redirect_info = get_redirect_info();

        if(redirect_info[index].enable == 1){
            std::vector<uint16_t>* arfcnList = new std::vector<uint16_t>;

            int i = 0;
            for( ; i < 5 ; ++i)
            {
                if(redirect_info[index].freqList[i] != 0)
                {
                    arfcnList->push_back(redirect_info[index].freqList[i]);
                }
                
            }

            if(! bbu.buildAndSendUeRedire(true, (uint8_t *)&redirect_info[index].ranType, (uint8_t *)&redirect_info[index].band, arfcnList, NULL)){
                // error
                EMLogError("buildAndSendUeRedire fail!");
            }

            delete(arfcnList);

        //    EMLogNotice("Live set redirect config info!");
        }


    }
    else
    {
        bbu.setWorking(false);
        EMLogInfo("BBU[%d]: Fail to config cell. RC=%d", bbu.getInstance().getSlotId(), static_cast<uint32_t>(rc));
        responseParas.push_back(WrapperCmdPara(PARA_TYPE_RESULT, static_cast<uint32_t>(PARA_VALUE_RESULT_FAILED)));
        StateReportProcedurePtr->reportState(bbu, BBU_READY);
    }
    if( isTrgByOam_ )
    {
        isTrgByOam_ = false;
        EutranMgrPtr->responseToSrcModule(CMD_SET_RESPONSE, responseParas);
    }
}

void OamManager::processSoftwareVerRpt(OamMessageProtocol_VersionRpt& verRpt, uint32_t slotId)
{
    std::string version;
    std::string phyVer;
    std::string kernelVer;
    std::string hwVer;
    if( !verRpt.unpack(version, phyVer, kernelVer, hwVer) )
    {
        EMLogError("Fail to unpack VersionRpt");

        if( isTrgByOam_ )
        {
            isTrgByOam_ = false;

            std::vector < WrapperCmdPara > responseParas;
            responseParas.push_back(WrapperCmdPara(PARA_TYPE_RESULT, static_cast<uint32_t>(PARA_VALUE_RESULT_FAILED)));
            responseParas.push_back(WrapperCmdPara(PARA_TYPE_EUTRAN_BBU_SLOT_ID, static_cast<uint8_t>(slotId)));
            EutranMgrPtr->responseToSrcModule(CMD_GET_RESPONSE, responseParas);
            return;
        }
    }

    EMLogInfo("BBU[%d] Software version is %s", slotId, version.c_str());
    if( isTrgByOam_ )
    {
        isTrgByOam_ = false;

        std::vector < WrapperCmdPara > responseParas;
        responseParas.push_back(WrapperCmdPara(PARA_TYPE_RESULT, static_cast<uint32_t>(PARA_VALUE_RESULT_SUCCESS)));
        responseParas.push_back(WrapperCmdPara(PARA_TYPE_EUTRAN_BBU_SLOT_ID, static_cast<uint8_t>(slotId)));

        responseParas.push_back(WrapperCmdPara(PARA_TYPE_EUTRAN_SOFTWARE_VERSION, version.length(), reinterpret_cast<uint8_t*>(const_cast<char*>(version.c_str()))));
        responseParas.push_back(WrapperCmdPara(PARA_TYPE_EUTRAN_PHY_VER, phyVer.length(), reinterpret_cast<uint8_t*>(const_cast<char*>(phyVer.c_str()))));
        responseParas.push_back(WrapperCmdPara(PARA_TYPE_EUTRAN_KERNEL_VER, kernelVer.length(), reinterpret_cast<uint8_t*>(const_cast<char*>(kernelVer.c_str()))));
        responseParas.push_back(WrapperCmdPara(PARA_TYPE_EUTRAN_HARDWARE_VER, hwVer.length(), reinterpret_cast<uint8_t*>(const_cast<char*>(hwVer.c_str()))));
        EutranMgrPtr->responseToSrcModule(CMD_GET_RESPONSE, responseParas);
    }
}

void OamManager::processTxPowerDbCfgRsp(OamMessageProtocol_TxPowerDbmConfigRsp& rsp, BbuCtrl& bbu)
{
    uint8_t rc = 0;
    if( !rsp.unpack(rc) )
    {
        EMLogError("Fail to unpack OamMessageProtocol_TxPowerDbmConfigRsp");
        EutranMgrPtr->responseFailure();
    }

    EMLogInfo("BBU[%d]: RC of TxPowerDbmConfig is [%d]", bbu.getInstance().getSlotId(), static_cast<uint32_t>(rc));
    if( rc!=0 )
    {
        EutranMgrPtr->responseFailure();
    }
    else
    {
        EutranMgrPtr->responseSuccess();
    }
}

void OamManager::processUeIdFilterRsp(OamMessageProtocol_UeIdFilterSwitchCfgRsp& rsp, BbuCtrl& bbu)
{
    uint8_t rc = 0;
    if( !rsp.unpack(rc) )
    {
        EMLogError("Fail to unpack OamMessageProtocol_UeIdFilterSwitchCfgRsp");
        EutranMgrPtr->responseFailure();
    }

    EMLogInfo("BBU[%d]: RC of UeIdFilterSwitchCfgRsp is [%d]", bbu.getInstance().getSlotId(), static_cast<uint32_t>(rc));
    if( rc!=0 )
    {
        EutranMgrPtr->responseFailure();
    }
    else
    {
        EutranMgrPtr->responseSuccess();
    }
}

void OamManager::processBbuStatusRpt(OamMessageProtocol_SysStatusRsp& rpt, BbuCtrl& bbu)
{
    SnifferMgrPtr->processBbuStateRsp(bbu, rpt);

    StateReportProcedurePtr->processMessage(rpt.getMessage(), bbu);
}

void OamManager::processBbuUpgradeRsp(OamMessageProtocol_SoftwareUpgradRsp& rsp, BbuCtrl& bbu)
{
    std::vector < WrapperCmdPara > responseParas;
    uint8_t rc = 0;
    if( !rsp.unpack(rc) )
    {
        EMLogError("Fail to unpack SoftwareUpgradRsp");
        responseParas.push_back(WrapperCmdPara(PARA_TYPE_RESULT, static_cast<uint32_t>(PARA_VALUE_RESULT_FAILED)));
    }
    else
    {
        EMLogInfo("SoftwareUpgradRsp rc=%d", static_cast<uint32_t>(rc));

        if( rc==0 )
        {
            responseParas.push_back(WrapperCmdPara(PARA_TYPE_RESULT, static_cast<uint32_t>(PARA_VALUE_RESULT_SUCCESS)));

            bbu.indicateDeactive();
        }
        else
        {
            responseParas.push_back(WrapperCmdPara(PARA_TYPE_RESULT, static_cast<uint32_t>(PARA_VALUE_RESULT_FAILED)));
        }
    }   

    if( isTrgByOam_ )
    {
        isTrgByOam_ = false;
        EutranMgrPtr->responseToSrcModule(CMD_SET_RESPONSE, responseParas);
    }
}

void OamManager::processEquitResetRsp(OamMessageProtocol_EquipResetRsp& rsp, BbuCtrl& bbu)
{
    uint8_t rc = 0;
    if( !rsp.unpack(rc) )
    {
        EMLogError("Fail to unpack EquipResetRsp");
        if( isTrgByOam_ )
        {
            isTrgByOam_ = false;
            EutranMgrPtr->responseFailure();
        }
        return;
    }

    EMLogInfo("RC of EquipResetRsp is %d", static_cast<uint32_t>(rc));
    if( rc==0 )
    {
        if( isTrgByOam_ )
        {
            isTrgByOam_ = false;
            EutranMgrPtr->responseSuccess();
        }

        bbu.indicateDeactive();
    }
    else
    {
        if( isTrgByOam_ )
        {
            isTrgByOam_ = false;
            EutranMgrPtr->responseFailure();
        }
    }
}

void OamManager::processSyncModeSettingRsp(OamMessageProtocol_SyncModeRsp& rsp, BbuCtrl&)
{
    uint8_t rc = 2;
    if( !rsp.unpack(rc) )
    {
        EMLogError("Fail to unpack SyncModeRsp");
    }

    EMLogInfo("RC of sync mode setting is %d", static_cast<uint32_t>(rc));
    if( rc==0 )
    {
        if( isTrgByOam_ )
        {
            isTrgByOam_ = false;
            EutranMgrPtr->responseSuccess();
        }
    }
    else
    {
        if( isTrgByOam_ )
        {
            isTrgByOam_ = false;
            EutranMgrPtr->responseFailure();
        }
    }
}

void OamManager::processSyncStateRsp(OamMessageProtocol_SyncStatusRsp& rsp, BbuCtrl& bbu)
{
    uint8_t typeCode = 0;
    uint8_t stateCode = 0;
    uint16_t syncArfcn = 0;
    uint16_t syncPci = 0;
    uint16_t syncRssi = 0;
    uint16_t syncTac = 0;
    if( !rsp.unpack(typeCode, stateCode, syncArfcn, syncPci, syncRssi, syncTac) )
    {
        EMLogError("Fail to unpack SyncStatusRsp");

        if( isTrgByOam_ )
        {
            isTrgByOam_ = false;
            EutranMgrPtr->responseFailure();
        }
        return;
    }

    EMLogInfo("SyncStatusRsp: typeCode[%d] - stateCode[%d]", static_cast<uint32_t>(typeCode), static_cast<uint32_t>(stateCode));
    if( isTrgByOam_ )
    {
        isTrgByOam_ = false;
        std::vector < WrapperCmdPara > responseParas;
        responseParas.push_back(WrapperCmdPara(PARA_TYPE_RESULT, static_cast<uint32_t>(PARA_VALUE_RESULT_SUCCESS)));
        responseParas.push_back(WrapperCmdPara(PARA_TYPE_EUTRAN_BBU_SLOT_ID, static_cast<uint8_t>(bbu.getInstance().getSlotId())));
        responseParas.push_back(WrapperCmdPara(PARA_TYPE_EUTRAN_SYNC_STATE_TYPE_CODE, typeCode));
        responseParas.push_back(WrapperCmdPara(PARA_TYPE_EUTRAN_SYNC_STATE_CODE, stateCode));
        responseParas.push_back(WrapperCmdPara(PARA_TYPE_EUTRAN_DL_ARFCN, syncArfcn));
        responseParas.push_back(WrapperCmdPara(PARA_TYPE_EUTRAN_PCI, syncPci));
        responseParas.push_back(WrapperCmdPara(PARA_TYPE_EUTRAN_SNIFFER_RSSI, syncRssi));
        responseParas.push_back(WrapperCmdPara(PARA_TYPE_EUTRAN_TAC, syncTac));
        EutranMgrPtr->responseToSrcModule(CMD_GET_RESPONSE, responseParas);
    }
    
}

void OamManager::processGpsStateRsp(OamMessageProtocol_GpsInfoRpt& rpt, BbuCtrl& bbu)
{
    uint8_t state = 0;
    int32_t longitude = 0;
    int32_t latitude = 0;

    std::vector < WrapperCmdPara > responseParas;
    if( !rpt.unpack(state, longitude, latitude) )
    {
        EMLogError("Fail to unpack GpsInfoRpt");
        responseParas.push_back(WrapperCmdPara(PARA_TYPE_RESULT, static_cast<uint32_t>(PARA_VALUE_RESULT_FAILED)));
        EutranMgrPtr->responseToSrcModule(CMD_GET_RESPONSE, responseParas);
    }
    else
    {
        float flong = (float)longitude/100000;
        float falt = (float)latitude/100000;
        int ildegree = (int)flong;
        int iadegree = (int)falt;

        flong = (flong - ildegree) * 100;
        falt = (falt - iadegree) * 100;

        int ilmin = (int)flong;
        int iamin = (int)falt;

        flong = (flong - ilmin) * 100;
        falt = (falt - iamin) * 100;


        float fl = 0, fa = 0;
        fl = ildegree + (float)ilmin/60  + (float)flong/3600;
        fa = iadegree + (float)iamin/60 + (float)falt/3600;
        longitude = fl * 100000;
        latitude = fa * 100000;
        EMLogInfo("State: %d; longitude: %d; latitude: %d", static_cast<uint32_t>(state), longitude, latitude);

        responseParas.push_back(WrapperCmdPara(PARA_TYPE_RESULT, static_cast<uint32_t>(PARA_VALUE_RESULT_SUCCESS)));
        responseParas.push_back(WrapperCmdPara(PARA_TYPE_EUTRAN_GPS_LONGTITUDE, static_cast<uint32_t>(longitude)));
        responseParas.push_back(WrapperCmdPara(PARA_TYPE_EUTRAN_GPS_LATITUDE, static_cast<uint32_t>(latitude)));
        EutranMgrPtr->responseToSrcModule(CMD_GET_RESPONSE, responseParas);
    }
}

void OamManager::processStdTxPowerDbGetRsp(OamMessageProtocol_TxPowerDbmStdGetRsp& msg, BbuCtrl& bbu)
{
    int8_t stdTxPowerDb = 0;
    if( !msg.unpack(stdTxPowerDb) )
    {
        EMLogError("Fail to unpack OamMessageProtocol_TxPowerDbmStdGetRsp");
        EutranMgrPtr->responseFailure();
    }
    else
    {
        EMLogInfo("BBU[%d]: STD TX power DB is %d", bbu.getInstance().getSlotId(), static_cast<int32_t>(stdTxPowerDb));
        std::vector < WrapperCmdPara > responseParas;
        responseParas.push_back(WrapperCmdPara(PARA_TYPE_RESULT, static_cast<uint32_t>(PARA_VALUE_RESULT_SUCCESS)));
        responseParas.push_back(WrapperCmdPara(PARA_TYPE_EUTRAN_STD_TX_POWER_DB, stdTxPowerDb));
        EutranMgrPtr->responseToSrcModule(CMD_GET_RESPONSE, responseParas);
    }
}

void OamManager::processStdTxPowerGetRsp(OamMessageProtocol_TxPowerStdGetRsp& msg, BbuCtrl& bbu)
{
    uint8_t stdTxPower = 0;
    if( !msg.unpack(stdTxPower) )
    {
        EMLogError("Fail to unpack OamMessageProtocol_TxPowerStdRsp");
        EutranMgrPtr->responseFailure();
    }
    else
    {
        EMLogInfo("BBU[%d]: STD TX power is %d", bbu.getInstance().getSlotId(), static_cast<uint32_t>(stdTxPower));
        std::vector < WrapperCmdPara > responseParas;
        responseParas.push_back(WrapperCmdPara(PARA_TYPE_RESULT, static_cast<uint32_t>(PARA_VALUE_RESULT_SUCCESS)));
        responseParas.push_back(WrapperCmdPara(PARA_TYPE_EUTRAN_STD_TX_POWER, stdTxPower));
        EutranMgrPtr->responseToSrcModule(CMD_GET_RESPONSE, responseParas);
    }
}

void OamManager::processStdTxPowerCfgRsp(OamMessageProtocol_TxPowerStdCfgRsp& msg, BbuCtrl& bbu)
{
    uint8_t rc = 0;
    if( !msg.unpack(rc) )
    {
        EMLogError("Fail to unpack OamMessageProtocol_TxPowerStdRsp");
        EutranMgrPtr->responseFailure();
    }
    else if( rc==0 )
    {
        EMLogInfo("BBU[%d]: RC[%d] from STD TX power config", bbu.getInstance().getSlotId(), static_cast<uint32_t>(rc));
        EutranMgrPtr->responseSuccess();
    }
    else
    {
        EMLogInfo("BBU[%d]: RC[%d] from STD TX power config", bbu.getInstance().getSlotId(), static_cast<uint32_t>(rc));
        EutranMgrPtr->responseFailure();
    }
}


bool OamManager::configCell(uint8_t slotId, uint16_t dlArfcn, uint16_t ulArfcn, uint16_t pci, uint16_t tac, 
                                 std::vector<uint32_t>& plmnList, 
                                 const std::vector<uint16_t>& intraFreqPci, 
                                 const std::vector<uint16_t>& interFreq,
                                 int16_t* txPwPtr)
{
    std::stringstream ss;

    ss << "slotId=" << static_cast<uint32_t>(slotId) << " dlArfcn=" << dlArfcn << " ulArfcn=" << ulArfcn << " pci=" << pci << " tac=" << tac;

    ss << " [PCI of intra freq: "; 
    for(size_t i=0; i<intraFreqPci.size(); i++)
    {
        ss << intraFreqPci[i] << "; ";
    }

    ss << "] [Earfcn of inter freq: ";
    for(size_t i=0; i<interFreq.size(); i++)
    {
        ss << interFreq[i] << "; ";
    }

    ss << "] ";

    if( txPwPtr!=NULL )
    {
        ss << "TX-power=" << *txPwPtr << ";";
    }

    EMLogInfo("%s", ss.str().c_str());

    BbuCtrl* bbu = BbuManagerPtr->getBbu(slotId);
    if( bbu==NULL )
    {
        EMLogError("Fail to get BBU from slot-id[%d]", static_cast<uint32_t>(slotId));
        return false;
    }

    if( !bbu->getInstance().isActive() )
    {
        EMLogInfo("BBU[slot=%d] is not up", static_cast<uint32_t>(slotId));
        return false;
    }

    NmmToX86Protocol_CellConfig cellConfig;
    uint32_t seqNo = bbu->getInstance().allocSeqNo();
    cellConfig.packSeqNum(seqNo);
    if( !cellConfig.pack(dlArfcn, ulArfcn, pci, plmnList, tac, intraFreqPci, interFreq));
    {
        EMLogError("Fail to pack NmmToX86Protocol_CellConfig");
        return false;
    }

    if( txPwPtr!=NULL )
    {
        if( !cellConfig.pack(*txPwPtr) )
        {
            EMLogError("Fail to pack NmmToX86Protocol_CellConfig");
            return false;
        } 
    }

    if( !bbu->getInstance().sendMessage(cellConfig.getMessage()) )
    {
        EMLogError("Fail to send message");
        return false;
    }
    StateReportProcedurePtr->reportState(*bbu, BBU_CELL_CFG);

    return true;
}

bool OamManager::UpdateCell(uint8_t slotId, std::vector<uint32_t>* plmnList, uint16_t* tac, uint16_t* earfcn, 
                                                   uint16_t* ulEarfcn, bool* measEnablePtr)
{
    if( plmnList==NULL && tac==NULL && earfcn==NULL && ulEarfcn==NULL && measEnablePtr!=NULL )
    {
        EMLogWarning("All parameters of cell update msg is not NULL");
        return false;
    }

    std::stringstream ss;
    ss << "Update cell to BBU[" << static_cast<uint32_t>(slotId) << "]: ";

    if( plmnList!=NULL )
    {
        ss << "no of plmnId=" << plmnList->size() << "; ";
    }

    if( tac!=NULL )
    {
        ss << "tac=" << *tac << "; ";
    }

    if( earfcn!=NULL )
    {
        ss << "earfcn=" << *earfcn << "; ";
    }

    if( ulEarfcn!=NULL )
    {
        ss << "ulEarfcn=" << *ulEarfcn << ";";
    }

    if( measEnablePtr!=NULL )
    {
        ss << "measEnable=" << *measEnablePtr << ";";
    }

    EMLogInfo("%s", ss.str().c_str());

    BbuCtrl* bbu = BbuManagerPtr->getBbu(slotId);
    if( bbu==NULL )
    {
        EMLogError("Fail to get BBU from slot-id[%d]", static_cast<uint32_t>(slotId));
        return false;
    }

    if( !bbu->getInstance().isActive() )
    {
        EMLogInfo("BBU[slot=%d] is not up", static_cast<uint32_t>(slotId));
        return false;
    }

    NmmToX86Protocol_CellUpdate update;
    if( !update.pack(plmnList, tac, earfcn, ulEarfcn, measEnablePtr) )
    {
        EMLogError("Fail to pack NmmToX86Protocol_CellUpdate");
        return false;
    }

    uint32_t seqNo = bbu->getInstance().allocSeqNo();
    update.packSeqNum(seqNo);

    if( !bbu->getInstance().sendMessage(update.getMessage()) )
    {
        EMLogError("Fail to send message");
        return false;
    }

    return true;
}

OamManager* OamManager::setTrgByOam(bool isTrig)
{
    isTrgByOam_ = isTrig;
    return this;
}

bool OamManager::shutDownTxPwer(BbuCtrl& bbu)
{
    EMLogInfo("BBU[%d]: shutdown TX power", bbu.getInstance().getSlotId());
    
    if( !bbu.buildAndSendTxPowerDb(127) )
    {
        EMLogError("BBU[%d]: Fail to send Tx Power message", bbu.getInstance().getSlotId());
        return false;
    }

    return true;
}

bool OamManager::registerMsgHandler(TlvMessage::Protocol_t protocol, TlvMessage::Signal_t signalType, EmBaseProcedure* proc)
{
    if( proc==NULL )
    {
        EMLogError("NULL pointer");
        return false;
    }
    if( signalType==OamMessageProtocol_Signal::INVALID || signalType>OamMessageProtocol_Signal::MAX_SIGNAL )
    {
        EMLogError("Invalid signalType[%d]", static_cast<uint32_t>(signalType));
        return false;
    }

    if( protocol!=OamMessageProtocol_Signal::TLV_PROTOCOL_NUMBER || protocol!=NmmToX86Protocol_Signal::TLV_PROTOCOL_NUMBER )
    {
        EMLogError("Invalid protocol[%d]", static_cast<uint32_t>(protocol));
        return false;
    }

    EMLogInfo("Resigter msg[%d - %d] to proc[%s]", static_cast<uint32_t>(protocol), static_cast<uint32_t>(signalType), proc->getName().c_str());

    uint16_t key = protocol;
    key = (key << 8)|signalType;
    std::map<uint16_t, std::list<EmBaseProcedure*> >::iterator fit = procHandlers_.find(key);
    if( fit==procHandlers_.end() )
    {
        std::list<EmBaseProcedure*> procs;
        procs.push_back(proc);
        procHandlers_[key] = procs;
    }
    else
    {
        procHandlers_[key].push_back(proc);
    }

    return true;
}
